﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wq.Extensions.Common;
using Wq.Extensions.Repository;
using Wq.ManagerService;
using Wq.ManagerService.Entities;
using Wq.ManagerService.Models;
using Wq.Model;

namespace Wq.Application
{
    public class ManagerApplication : BaseApplication
    {
        private readonly RoleService roleService;
        private readonly Wq.ManagerService.ManagerService managerService;
        private readonly RedisBaseRepository redisRepository;
        private readonly LogService logService;

        public ManagerApplication(RoleService roleService,
            Wq.ManagerService.ManagerService managerService,
            RedisBaseRepository redisRepository,
            LogService logService)
        {
            this.roleService = roleService;
            this.managerService = managerService;
            this.redisRepository = redisRepository;
            this.logService = logService;
        }

        #region 权限组

        /// <summary>
        /// 添加权限组
        /// </summary>
        /// <param name="role"></param>
        /// <returns></returns>
        public void SaveRole(RoleEditor role)
        {
            Verify(role);
            if (role.Id > 0)
                roleService.Save(role);
            else
                roleService.Create(role);
        }

        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="editor"></param>
        /// <exception cref="MyException"></exception>

        public void Verify(RoleEditor editor)
        {
            if (string.IsNullOrEmpty(editor.Name))
                throw new MyException("权限组名称不能空");
        }

        /// <summary>
        /// 获取权限组
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public MessageModel Details(long id)
        {
            var privileges = roleService.GetPrivilege();
            var role = roleService.Details(id);
            return new MessageModel
            {
                Data = new { Privileges = privileges, Role = role }
            };

        }

        /// <summary>
        /// 获取权限组列表
        /// </summary>
        /// <returns></returns>
        public MessageModel GetRoles()
        {
            return new MessageModel
            {
                Data = roleService.GetList()
            };
        }

        /// <summary>
        /// 删除权限组
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public void DeleteRole(long id)
        {
            var model = roleService.GetById(id);
            if (model.Number > 0)
                throw new MyException("权限组下面存在管理员不能进行删除");
            roleService.Delete(id);
        }


        /// <summary>
        /// 获取某个会员下的权限路径
        /// </summary>
        /// <param name="managerId"></param>
        /// <returns></returns>
        public List<Menu> GetUsableMenus(long managerId)
        {
            var privileges = roleService.GetPrivilege();
            var manager = managerService.GetById(managerId);

            if (manager.RoleId > 0)
            {
                List<RolePrivilegeInfo> rolePrivilege = roleService.GetRolePrivilege(manager.RoleId);
                List<Menu> menus = new List<Menu>();
                privileges.ForEach(item => {
                    var oneMenu = GetMenu(item, rolePrivilege);
                    if (item.Children != null)
                    {
                        item.Children.ForEach(two => {
                            var towMenu = GetMenu(two, rolePrivilege);

                            #region 三级目录
                            if (two.Children != null)
                            {
                                two.Children.ForEach(three => {
                                    var threeMenu = GetMenu(three, rolePrivilege);
                                    if (threeMenu != null)
                                    {
                                        if (towMenu == null)
                                            towMenu = Assignment(two, rolePrivilege);
                                        if (towMenu.Children == null) towMenu.Children = new List<Menu>();
                                        towMenu.Children.Add(threeMenu);
                                    }
                                });
                            }

                            #endregion

                            if (towMenu != null)
                            {
                                if (oneMenu == null)
                                    oneMenu = Assignment(item, rolePrivilege);
                                if (oneMenu.Children == null) oneMenu.Children = new List<Menu>();
                                oneMenu.Children.Add(towMenu);
                            }

                        });
                    }

                    if (oneMenu != null)
                        menus.Add(oneMenu);

                });

                return menus;
            }

            return privileges;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="children"></param>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public Menu GetMenu(Menu children, List<RolePrivilegeInfo> rolePrivilege)
        {
            Menu menu = null;
            var roles = rolePrivilege.Select(p => p.Route).Distinct().ToList();

            if (roles.Contains(children.Route))
            {
                menu = Assignment(children, rolePrivilege);
            }
            return menu;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public Menu Assignment(Menu source, List<RolePrivilegeInfo> rolePrivilege)
        {
            var privileges = rolePrivilege.Where(p => p.Route == source.Route).Select(p => p.Privilege).Distinct().ToList();
            return new Menu()
            {
                Route = source.Route,
                Name = source.Name,
                Path = source.Path,
                Icon = source.Icon,
                Permissions = source.Permissions?.Where(p => privileges.Contains(p.Id)).ToList(),
                Children = null
            };
        }

        /// <summary>
        /// 记录日志
        /// </summary>
        /// <param name="oldManager"></param>
        /// <param name="newManager"></param>
        public void Log(ManagerEditor oldManager, ManagerEditor newManager = null, bool isDelete = false)
        {
            string msg = string.Empty;
            if (isDelete)
                msg = $"删除管理员【{oldManager.Username}】";
            else
            {
                if (newManager.Id == 0)
                    msg = $"新增管理员【{newManager.Username}】";
                else
                {
                    msg = $"修改管理员【{oldManager.Username}】：";
                    if (!string.IsNullOrEmpty(newManager.Password))
                        msg += "修改密码";
                    if (oldManager.RoleId != newManager.RoleId)
                    {
                        if (newManager.RoleId == 0)
                            msg += $" 角色由【{oldManager.RoleName}】变为【超级管理员】";
                        else
                        {
                            var role = roleService.GetById(newManager.RoleId);
                            msg += $" 角色由【{oldManager.RoleName}】变为【{role.Name}】";
                        }
                    }
                }
            }

            logService.Create(LogModule.Manager, msg);
        }

        #endregion

        #region 管理员

        /// <summary>
        /// 管理员列表
        /// </summary>
        /// <param name="pageModel"></param>
        /// <returns></returns>
        public MessageModel List(PageModel<ManagerQuery> pageModel)
        {
            int count = 0;
            return new MessageModel { Data = managerService.List(pageModel, ref count), Count = count };
        }

        /// <summary>
        /// 添加保存管理员
        /// </summary>
        /// <param name="manager"></param>
        /// <returns></returns>
        public void SaveManager(ManagerEditor manager)
        {
            ManagerVerify(manager);
            var old = managerService.Details(manager.Id);
            if (manager.Id > 0)
                managerService.Save(manager);
            else
                managerService.Create(manager);
            Log(old, manager);
        }

        /// <summary>
        /// 添加编辑管理员
        /// </summary>
        /// <param name="login"></param>
        /// <returns></returns>
        public void ManagerVerify(ManagerEditor manager)
        {
            //检查输入合法性
            if (string.IsNullOrWhiteSpace(manager.Username))
                throw new MyException("请填写用户名");
            manager.Username = manager.Username.Trim(); //清除空格
            if (string.IsNullOrWhiteSpace(manager.Password) && manager.Id == 0)
                throw new MyException("请填写密码");
            manager.Password = manager.Password.Trim(); //清除空格

            if (manager.Id == 0 && managerService.Count(p => p.UserName == manager.Username) > 0)
                throw new MyException("用户名已存在");
            if (manager.Id > 0 && managerService.Count(p => p.UserName == manager.Username && p.Id != manager.Id) > 0)
                throw new MyException("用户名已存在");

        }


        /// <summary>
        /// 删除管理员
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public void RemoveManager(long id)
        {
            var old = managerService.Details(id);
            managerService.Delete(id);
            Log(old, isDelete: true);
        }

        /// <summary>
        /// 获取Token
        /// </summary>
        /// <param name="login"></param>
        /// <returns></returns>
        public MessageModel GetToken(string name, string password)
        {

            var manager = managerService.GetFirst(p => p.UserName == name);
            if (manager == null)
                throw new MyException("用户不存在");
            password = EncryptionHelper.GetPasswrodWithTwiceEncode(password, manager.PasswordSalt);
            if (manager.Password != password)
                throw new MyException("密码错误");
            string access_token = JWTHelper.IssueJwt(new JwtUserModel
            {
                UserId = manager.Id.ObjToString(),
                UserRole = "Manager",
                UserName = manager.UserName,
                UserBirthDay = DateTime.Now
            });
            var refresh_token = Guid.NewGuid().ToString("N");
            var refreshToken = new RefreshToken()
            {
                Token = refresh_token,
                UserId = manager.Id
            };

            Task task = redisRepository.Set(SysCacheKey.RefreshToken(refresh_token), refreshToken, TimeSpan.FromMinutes(60));
            var expire = double.Parse(AppSettings.app("JwtSettings:Expire"));

            return new MessageModel { Data = new { AccessToken = access_token, RefreshToken = refresh_token, UserName = name } };
        }



        /// <summary>
        /// 刷新Token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public MessageModel RefreshToken(string token)
        {

            var refreshToken = redisRepository.Get<RefreshToken>(SysCacheKey.RefreshToken(token)).Result;
            if (refreshToken == null)
                return new MessageModel { Success = false, Msg = "token已过期" };
            else
            {
                var manager = managerService.GetFirst(p => p.Id == refreshToken.UserId);
                string access_token = JWTHelper.IssueJwt(new JwtUserModel
                {
                    UserId = manager.Id.ObjToString(),
                    UserRole = "Manager",
                    UserName = manager.UserName,
                    UserBirthDay = DateTime.Now
                });
                var refresh_token = Guid.NewGuid().ToString("N");
                var newtoken = new RefreshToken()
                {
                    Token = refresh_token,
                    UserId = manager.Id

                };
                Task task = redisRepository.Set(SysCacheKey.RefreshToken(refresh_token), newtoken, TimeSpan.FromMinutes(60));
                var expire = double.Parse(AppSettings.app("JwtSettings:Expire"));
                return new MessageModel { Data = new { AccessToken = access_token, RefreshToken = refresh_token } };

            }
        }
        #endregion
    }
}
